import { TraverseDeepRecursionOptionsType, CommonUtil } from '../../common'
import { FunUtil } from '../../fun'
import { ObjUtil } from '../../obj'
import { traverseDeepRecursion as objTraverseDeepRecursion } from '../../obj/utils/traverse-deep-recursion'

export const traverseDeepRecursion = (arr: any[], options: TraverseDeepRecursionOptionsType) => {
  const {
    undefinedHandler,
    nullHandler,
    funHandler,
    excludeObjProps,
    includeObjProps,
    objPreHandler,
    excludeArrItemHandler,
    arrPreHandler,
    otherHandler,
    getStop,
    setStop
  } = {
    undefinedHandler: () => {},
    nullHandler: () => {},
    funHandler: () => {},
    excludeObjProps: [],
    includeObjProps: [],
    objPreHandler: () => {},
    excludeArrItemHandler: () => false,
    arrPreHandler: () => {},
    otherHandler: () => {},
    ...options
  }
  for (let i = 0; i < arr.length; i++) {
    if (getStop()) return
    const item = arr[i]
    if (excludeArrItemHandler(item)) continue
    else if (CommonUtil.isUndefined(item)) undefinedHandler(item, i, setStop)
    else if (CommonUtil.isNull(item)) nullHandler(item, i, setStop)
    else if (FunUtil.isFun(item)) funHandler(item, i, setStop)
    else if (Array.isArray(item)) {
      arrPreHandler(item, i, arr, setStop)
      traverseDeepRecursion(item, {
        undefinedHandler,
        nullHandler,
        funHandler,
        excludeObjProps,
        includeObjProps,
        objPreHandler,
        excludeArrItemHandler,
        arrPreHandler,
        otherHandler,
        getStop,
        setStop
      })
    } else if (ObjUtil.isObj(item)) {
      objPreHandler(item, i, arr, setStop)
      objTraverseDeepRecursion(item, {
        undefinedHandler,
        nullHandler,
        funHandler,
        excludeObjProps,
        includeObjProps,
        objPreHandler,
        excludeArrItemHandler,
        arrPreHandler,
        otherHandler,
        getStop,
        setStop
      })
    } else otherHandler(item, i, setStop)
  }
}
